using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using System.IO;

namespace WindowsApplication1
{
    public partial class frmBlackJackSim : Form
    {
        public double TCAdjustment = 1;
        public int shoes = 0;
        public int currentCount = 0;
        public double decksLeft = 0;
        public double trueCount = 0;
        public bool playerCounts = false;
        public bool errorOn = false;
        public int errorRate = 0;
        double PlayerMoneyTotal = 0;
        Card cards = new Card();
        SimulationStats stats = new SimulationStats();
        public const int SplitHandTotal = -99;

        public frmBlackJackSim()
        {
            InitializeComponent();
        }

        private Card TakeCard(int CurrentCardPostion, Card[] FullShoe)
        {
            int CardValue = FullShoe[CurrentCardPostion].Value;
            
            //Keep a running count of the cards
            if ((CardValue > 1) && (CardValue < 7))
            {
                currentCount++;
            }
            else if ((CardValue > 9) || (CardValue == 1))
            {
                currentCount--;
            }

            return FullShoe[CurrentCardPostion]; 
        }


        private int PlayerHand(Card[] FullShoe, Player player, int DealerUpCard, int CurrentCardPosition, int NumberOfPreviousSplitsThisRound, out int NewCardPosition, out bool DoubleDown)
        {
            //CURRENT CARD POSITION
            NewCardPosition = CurrentCardPosition;

            //WINNER TRACKING
            player.Total = 0;

            //ACE TRACKING
            player.AceCount = 0;

            //SPLIT TRACKING
            player.CanSplit = false;
            String NotRelevant = null;

            //DOUBLE TRACKING
            DoubleDown = false;

            //REMOVE DOUBLE & SPLIT OPTION AFTER INITIAL HIT
            player.NumberOfCards = 2;

            //NEXT MOVE ACCORDING TO BASIC STRATEGY
            //String PlayerMove = null;

            //Count Aces
            player.CheckInitialAces();

            //Does player have option to split? (Set right now to prohibit splits after a split)
            if ((player.Peek(0).CardType == player.Peek(1).CardType) && (NumberOfPreviousSplitsThisRound < 1))
            {
                player.CanSplit = true;
            }

            //Total player's initial hand (counting all Aces as 11's)
            player.Total = (player.Peek(0).Value + player.Peek(1).Value + (player.AceCount * 10));

            //Find best move according to basic strategy
            player.MakeTheRightMove(DealerUpCard);

            //Execute correct move
            while (player.Move != Action.Stand.ToString())
            {
                if (player.Move == Action.Hit.ToString())
                {
                    TakeOneCard(FullShoe, player, ref NewCardPosition, ref NotRelevant);
                }
                else if (player.Move == Action.Double.ToString())
                {
                    TakeOneCard(FullShoe, player, ref NewCardPosition, ref NotRelevant);
                    DoubleDown = true;
                }
                else
                {
                    //Split Hand
                    return SplitHandTotal;
                }

                //Over21 and no Aces BUSTED
                if (player.Total > 21)
                {
                    if (player.AceCount == 0)
                    {
                        //Player Busts
                        CurrentCardPosition = NewCardPosition;
                        return (player.Total);
                    }
                    else
                    {
                        //Adjust for soft aces if applicable
                        player.Over21WithAce();
                    }
                }

                //Only allow one card to be drawn on double
                if (player.Move == Action.Double.ToString())
                {
                    break;
                }

                player.MakeTheRightMove(DealerUpCard);
            }
            //CurrentCardPosition = NewCardPosition;
            return (player.Total);
        }

        //Take one more card
        private void TakeOneCard(Card[] FullShoe, Player player, ref int NewCardPosition, ref String NotRelevant)
        {
            player.Add(TakeCard(NewCardPosition, FullShoe));
            NewCardPosition++;
            player.NumberOfCards++;
            player.Total = player.Total + player.Peek(player.Count - 1).Value;
            player.CheckNewAce();
        }

        private int DealerHand(Card[] FullShoe, Dealer dealer, bool DealerHitsSoft17, int currentCardPosition, out int cardPositionOUT)
        {
            //WINNER TRACKING
            dealer.Total = 0;
            
            //ACE TRACKING
            dealer.AceCount = 0;
            dealer.CheckInitialAces();

            //Calculate Initial Total
            dealer.Total = (dealer.Peek(0).Value + dealer.Peek(1).Value + (dealer.AceCount * 10));

            while (dealer.Total < 21)
            {
                if ((((dealer.Total > 16) && ((dealer.AceCount == 0) || (DealerHitsSoft17 == false))) || (dealer.Total > 17)) && (dealer.Total <= 21))
                    break;
                else
                {
                    dealer.Add(TakeCard(currentCardPosition, FullShoe));
                    currentCardPosition++;
                    dealer.Total = dealer.Total + dealer.Peek(dealer.Count - 1).Value;
                    dealer.CheckNewAce();
                    if (dealer.Total > 21)
                    {
                        if (dealer.AceCount == 0)
                        {
                            break;
                        }
                        else
                            dealer.Over21WithAce();
                    }
                }
            }
       
            cardPositionOUT = currentCardPosition;
            return (dealer.Total);
        }

        private void cmdDeal_Click(object sender, EventArgs e)
        {
            TCAdjustment = Convert.ToDouble(lblTCAdjustment.Text);
            currentCount = 0;
            trueCount = 0;
            stats.Shoes = 0;
            stats.LowestBankroll = 1000000000;
            stats.HighestBankroll = 0;
            stats.HighestBet = 0;
            stats.LowestCount = 0;
            stats.HighestCount = 0;
            stats.NumberOfErrors = 0;
            playerCounts = false;
            errorOn = false;
            errorRate = 0;

            bool updateGUIContinuously = false;
            

            if (rbCountTrue.Checked)
            {
                playerCounts = true;
            }
            if (chkGUIUpdate.Checked)
            {
                updateGUIContinuously = true;
            }
            if (rbErrorsOn.Checked) //Check to see if we are playing with human error
            {
                errorOn = true;
                errorRate = tbErrorRate.Value;
            }

            //Initial Setup
            rtbHandOutcome.Text = "";
            int NumOfRoundsToSim = 0;
            try
            {
                NumOfRoundsToSim = Convert.ToInt32(txtHandsToSim.Text);
            }
            catch
            {
                txtHandsToSim.Text = "100";
                NumOfRoundsToSim = 100;
            }
            if ((NumOfRoundsToSim < 1) || (NumOfRoundsToSim > 1000000000))
            {
                txtHandsToSim.Text = "100";
                NumOfRoundsToSim = 100;
            }
            Application.DoEvents();
            this.Update();
            
            stats.Pushes = 0;
            stats.DealerWins = 0;
            stats.PlayerWins = 0;
            stats.Splits = 0;
            stats.PlayerBlackJacks = 0;
            stats.WinningDoubles = 0;
            stats.LosingDoubles = 0;
            stats.PushingDoubles = 0;

            bool DealerHitsSoft17 = false;
            if (rbTrue.Checked == true)
            {
                DealerHitsSoft17 = true;
            }
            double DecksAfterCut = 2;
            double CardsAfterCut = DecksAfterCut * 52;
            stats.Shoes = 0;
            rtbHandOutcome.Text = "";
            
            //Create First Shoe
            Card[] FullShoe = cards.createShoe(8);
            FullShoe = cards.shuffleDeck(FullShoe);
            stats.Shoes++;
            int TotalNumberOfCards = FullShoe.Length;
            int CutPosition = TotalNumberOfCards - (int)Math.Round(CardsAfterCut,0); //Finds how many cards remain after the cut card
            int CurrentCardPostion = 1; //Always discard the first card after shuffle
            
            //Funds Tracking
            PlayerMoneyTotal = Convert.ToInt32(txtStartingBankRoll.Text);
            double DealerMoneyTotal = 0;
            int TableMinimum = 10;
            int TableMaximum = 1000;
            int BettingUnit = 100;
            int TotalBankroll = 50000;
            //************
            
            try
            {
                TotalBankroll = Convert.ToInt32(txtStartingBankRoll.Text);
                BettingUnit = Convert.ToInt32(lblBettingUnit.Text);
                TableMinimum = Convert.ToInt32(txtTableMin.Text);
                TableMaximum = Convert.ToInt32(txtTableMax.Text);
            }
            catch
            {
                TotalBankroll = 50000;
                BettingUnit = 100;
                TableMinimum = 10;
                TableMaximum = 1000;
                txtStartingBankRoll.Text = "50000";
                txtTableMin.Text = "10";
                lblBettingUnit.Text = "100"; 
                txtTableMax.Text = "1000";
            }
            if ((TotalBankroll < 100) || (TotalBankroll > 10000000))
            {
                BettingUnit = 50000;
            }

            //Current Hand Totals
            //player.Total = 0;
            //int DealerTotal = 0;

            stats.Hand = 0;
            for (stats.Hand = 0; stats.Hand < NumOfRoundsToSim; stats.Hand++)
            {
                double PercentDone = (((double)stats.Hand / (double)NumOfRoundsToSim)*100);
                progressBar1.Value = (int)PercentDone;
                this.Update();

                if (CurrentCardPostion < CutPosition)
                {

                    //Bet is based on count if player is a counter
                    decksLeft = Math.Round(((double)(TotalNumberOfCards - CurrentCardPostion) / 52), 1);
                    int PlayerBet = BettingDecision(TableMinimum, TableMaximum, BettingUnit);

                    //Clear Flags
                    bool PlayerDouble = false;
                    bool PlayerBlackJack = false;
                    bool DealerBlackJack = false;
                    bool PlayerSplitHand = false;
                    bool SplitHand1Double = false;
                    bool SplitHand2Double = false;

                    //Split Tracking
                    int SplitHand1Total = 0;
                    int SplitHand2Total = 0;

                    //Draw Initial Cards
                    Player player = new Player();
                    Player player_Split1 = new Player();
                    Player player_Split2 = new Player();
                    Dealer dealer = new Dealer();
                    player.Add(TakeCard(CurrentCardPostion, FullShoe));
                    CurrentCardPostion++;
                    dealer.Add(TakeCard(CurrentCardPostion, FullShoe));
                    CurrentCardPostion++;
                    player.Add(TakeCard(CurrentCardPostion, FullShoe));
                    CurrentCardPostion++;
                    dealer.Add(TakeCard(CurrentCardPostion, FullShoe));
                    CurrentCardPostion++;

                    //Check for initial blackjacks
                    PlayerBlackJack = player.CheckBlackJack();
                    DealerBlackJack = dealer.CheckBlackJack();

                    //If the dealer's up card is an Ace, Offer insurance
                    if (dealer.Peek(0).Value == 1) 
                        InsuranceDecision(PlayerBet, DealerBlackJack);

                    //If we are playing with error do the calculation here
                    if (errorOn)
                    {
                        //See if player makes error based on applying user entered error percentage rate
                        RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();
                        int PRand = (GetNextInt32(rnd) % 100);
                        CountingErrorAdjustment(rnd, PRand);
                    }

                    //If neighther the dealer nor the player has a blackjack then proceed...
                    if ((DealerBlackJack == false) && (PlayerBlackJack == false))
                    {
                        int NewCardPosition = 0;
                        int NumberOfPreviousSplitsThisRound = 0;
                        player.Total = PlayerHand(FullShoe, player, dealer.Peek(0).Value, CurrentCardPostion, NumberOfPreviousSplitsThisRound, out NewCardPosition, out PlayerDouble);
                        CurrentCardPostion = NewCardPosition;

                        if (player.Total == SplitHandTotal)//We split the hands
                        {
                            stats.Splits++;
                            PlayerSplitHand = true;

                            //Draw 1 replacement card...
                            player_Split1.Add(player.Peek(0));
                            player_Split1.Add(TakeCard(CurrentCardPostion, FullShoe));
                            CurrentCardPostion++;

                            if (player_Split1.Peek(0).Value > 1) //If we split aces then the player only gets one card on each ace, no need to go through basic strategy rules...
                            {
                                //Play out new first hand (Blackjack does not pay 2 to 1 so we dont treat it individually)
                                NewCardPosition = 0;
                                NumberOfPreviousSplitsThisRound = 1;
                                SplitHand1Total = PlayerHand(FullShoe, player_Split1, dealer.Peek(0).Value, CurrentCardPostion, NumberOfPreviousSplitsThisRound, out NewCardPosition, out SplitHand1Double);
                                CurrentCardPostion = NewCardPosition;
                            }
                            else
                            {
                                SplitHand1Total = player_Split1.Peek(0).Value + 10 + player_Split1.Peek(1).Value;
                                if (player_Split1.Peek(1).Value == 1)
                                {
                                    SplitHand1Total = 2;
                                }
                            }

                            //Draw 1 replacement card (For hand 2) and Play out new second hand...
                            player_Split2.Add(player.Peek(0));
                            player_Split2.Add(TakeCard(CurrentCardPostion, FullShoe));
                            CurrentCardPostion++;

                            if (player_Split2.Peek(0).Value > 1) //If we did not split aces...
                            {
                                //Play out new second hand
                                NewCardPosition = 0;
                                NumberOfPreviousSplitsThisRound = 1;
                                SplitHand2Total = PlayerHand(FullShoe, player_Split2, dealer.Peek(0).Value, CurrentCardPostion, NumberOfPreviousSplitsThisRound, out NewCardPosition, out SplitHand2Double);
                                CurrentCardPostion = NewCardPosition;
                            }
                            else
                            {
                                SplitHand2Total = player_Split2.Peek(0).Value + 10 + player_Split2.Peek(1).Value;
                                if (player_Split2.Peek(1).Value == 1)
                                {
                                    SplitHand2Total = 2;
                                }
                            }
                        }
                        if ((player.Total <= 21) && (SplitHand1Total <= 21) && (SplitHand2Total <= 21)) //If player did not already bust and player does not have blackjack, play out dealer hand. (if no split occured, SplitHandTotals will be zero)
                        {
                            NewCardPosition = 0;
                            dealer.Total = DealerHand(FullShoe, dealer, DealerHitsSoft17, CurrentCardPostion, out NewCardPosition);
                            CurrentCardPostion = NewCardPosition;
                        }
                    }
                    
                    //Find winner and settle bets
                    bool PlayerWon = false;
                    bool Push = false;
                    bool PlayerWonSplit1 = false;
                    bool PlayerWonSplit2 = false;
                    bool PlayerPushSplit1 = false;
                    bool PlayerPushSplit2 = false;

                    if (PlayerSplitHand)
                    {
                        PlayerMoneyTotal -= PlayerBet; //Subtract base bet again because now we have two hands

                        //Settle Hand 1
                        int TempOriginalBet = PlayerBet;
                        if (SplitHand1Double)
                        {
                            PlayerMoneyTotal -= PlayerBet; //Remove another bettingUnit from stack for Double
                            PlayerBet = (PlayerBet * 2); //Adjust for new bet
                        }
                        if ((SplitHand1Total > 21) || ((SplitHand1Total < dealer.Total) && (dealer.Total <= 21)))
                        {
                            if (SplitHand1Double)
                            {
                                stats.LosingDoubles++;
                            }
                            stats.DealerWins++;
                            DealerMoneyTotal += PlayerBet;
                        }
                        else if ((dealer.Total > 21) || ((dealer.Total < SplitHand1Total) && (SplitHand1Total <= 21)))
                        {
                            if (SplitHand1Double)
                            {
                                stats.WinningDoubles++;
                            }
                            stats.PlayerWins++;
                            PlayerMoneyTotal += (PlayerBet * 2);
                            DealerMoneyTotal -= PlayerBet;
                            PlayerWon = true;
                            PlayerWonSplit1 = true;
                        }
                        else if (dealer.Total == SplitHand1Total)
                        {
                            if (SplitHand1Double)
                            {
                                stats.PushingDoubles++;
                            }
                            stats.Pushes++;
                            PlayerMoneyTotal += PlayerBet;
                            PlayerPushSplit1 = true;
                        }
                        //Settle Hand 2
                        PlayerBet = TempOriginalBet;
                        if (SplitHand2Double)
                        {
                            PlayerMoneyTotal -= PlayerBet; //Remove another bettingUnit from stack for Double
                            PlayerBet = (PlayerBet * 2); //Adjust for new bet
                        }
                        if ((SplitHand2Total > 21) || ((SplitHand2Total < dealer.Total) && (dealer.Total <= 21)))
                        {
                            if (SplitHand2Double)
                            {
                                stats.LosingDoubles++;
                            }
                            stats.DealerWins++;
                            DealerMoneyTotal += PlayerBet;
                        }
                        else if ((dealer.Total > 21) || ((dealer.Total < SplitHand2Total) && (SplitHand2Total <= 21)))
                        {
                            if (SplitHand2Double)
                            {
                                stats.WinningDoubles++;
                            }
                            stats.PlayerWins++;
                            PlayerMoneyTotal += (PlayerBet * 2);
                            DealerMoneyTotal -= PlayerBet;
                            PlayerWonSplit2 = true;
                        }
                        else if (dealer.Total == SplitHand2Total)
                        {
                            if (SplitHand2Double)
                            {
                                stats.PushingDoubles++;
                            }
                            stats.Pushes++;
                            PlayerMoneyTotal += PlayerBet;
                            PlayerPushSplit2 = true;
                        }

                    }
                    else
                    {
                        if (DealerBlackJack || PlayerBlackJack) //See if we need to answer blackjacks first
                        {
                            if (DealerBlackJack && PlayerBlackJack)
                            {
                                stats.Pushes++;
                                PlayerMoneyTotal += PlayerBet;
                                Push = true;
                            }
                            else if (DealerBlackJack && !PlayerBlackJack)
                            {
                                stats.DealerWins++;
                                DealerMoneyTotal += PlayerBet;
                            }
                            else if (PlayerBlackJack && !DealerBlackJack)
                            {
                                stats.PlayerWins++;
                                PlayerMoneyTotal += (PlayerBet + (PlayerBet * 1.5));
                                DealerMoneyTotal -= (PlayerBet * 1.5);
                                PlayerWon = true;
                                stats.PlayerBlackJacks++;
                            }
                        }
                        else //Check to see if player busted first, then dealer
                        {
                            if (PlayerDouble)
                            {
                                PlayerMoneyTotal -= PlayerBet; //Remove another bettingUnit from stack for Double
                                PlayerBet = (PlayerBet * 2); //Adjust for new bet
                            }
                            if ((player.Total > 21) || ((player.Total < dealer.Total) && (dealer.Total <= 21)))
                            {
                                if (PlayerDouble)
                                {
                                    stats.LosingDoubles++;
                                }
                                stats.DealerWins++;
                                DealerMoneyTotal += PlayerBet;
                            }
                            else if ((dealer.Total > 21) || ((dealer.Total < player.Total) && (player.Total <= 21)))
                            {
                                if (PlayerDouble)
                                {
                                    stats.WinningDoubles++;
                                }
                                stats.PlayerWins++;
                                PlayerMoneyTotal += (PlayerBet * 2);
                                DealerMoneyTotal -= PlayerBet;
                                PlayerWon = true;
                            }
                            else if (dealer.Total == player.Total)
                            {
                                if (PlayerDouble)
                                {
                                    stats.PushingDoubles++;
                                }
                                stats.Pushes++;
                                PlayerMoneyTotal += PlayerBet;
                                Push = true;
                            }
                        }
                    }

                    //OUTPUT (SHOW FIRST 100 HANDS ONLY)
                    if (stats.Hand < 10)
                    //if (PlayerBet > BettingUnit * 2)
                    //if (PlayerSplitHand)
                    {
                        rtbHandOutcome.Text += "Dealer: ";
                        for (int d = 0; d < dealer.Count; d++)
                        {
                            rtbHandOutcome.Text += dealer.Peek(d).Value + ", ";
                        }
                        rtbHandOutcome.Text += " \n";

                        if (PlayerSplitHand)
                        {
                            rtbHandOutcome.Text += "Player: " + player.Peek(0).Value + ", " + player.Peek(0).Value + " SPLIT\n";
                            rtbHandOutcome.Text += "Hand 1: ";
                            for (int p1 = 0; p1 < player_Split1.Count; p1++)
                            {
                                rtbHandOutcome.Text += player_Split1.Peek(p1).Value + ", ";
                            }
                            if (SplitHand1Double)
                            {
                                rtbHandOutcome.Text += " DOUBLE ";
                            }
                            rtbHandOutcome.Text += " \n";
                            if (PlayerWonSplit1)
                            {
                                rtbHandOutcome.Text += "PLAYER WINS!";
                            }
                            else if (PlayerPushSplit1)
                            {
                                rtbHandOutcome.Text += "PUSH!";
                            }
                            else
                            {
                                rtbHandOutcome.Text += "DEALER WINS!";
                            }
                            rtbHandOutcome.Text += " \n";
                            rtbHandOutcome.Text += "Hand 2: ";
                            for (int p2 = 0; p2 < player_Split2.Count; p2++)
                            {
                                rtbHandOutcome.Text += player_Split2.Peek(p2).Value + ", ";
                            }
                            if (SplitHand2Double)
                            {
                                rtbHandOutcome.Text += " DOUBLE ";
                            }
                            rtbHandOutcome.Text += " \n";
                            if (PlayerWonSplit2)
                            {
                                rtbHandOutcome.Text += "PLAYER WINS!";
                            }
                            else if (PlayerPushSplit2)
                            {
                                rtbHandOutcome.Text += "PUSH!";
                            }
                            else
                            {
                                rtbHandOutcome.Text += "DEALER WINS!";
                            }
                            rtbHandOutcome.Text += " \n";
                        }
                        else
                        {
                            rtbHandOutcome.Text += "Player: ";
                            for (int p = 0; p < player.Count; p++)
                            {
                                rtbHandOutcome.Text += player.Peek(p).Value + ", ";
                            }
                            if (PlayerDouble)
                            {
                                rtbHandOutcome.Text += " DOUBLE ";
                            }
                            rtbHandOutcome.Text += " \n";
                            if (PlayerWon)
                            {
                                rtbHandOutcome.Text += "PLAYER WINS!";
                            }
                            else if (Push)
                            {
                                rtbHandOutcome.Text += "PUSH!";
                            }
                            else
                            {
                                rtbHandOutcome.Text += "DEALER WINS!";
                            }
                        }

                        rtbHandOutcome.Text += " \n";
                        rtbHandOutcome.Text += "Bet: " + PlayerBet + "\n";
                        if (playerCounts)
                        {
                            rtbHandOutcome.Text += "True Count:" + trueCount + "\n";
                        }
                        rtbHandOutcome.Text += "Player Money Total: " + PlayerMoneyTotal + "\n";
                        rtbHandOutcome.Text += "Dealer Money Total: " + DealerMoneyTotal + "\n";
                        rtbHandOutcome.Text += " \n";
                    }
                    if (updateGUIContinuously)
                    {
                        //PLACEHOLDER
                    }
                }
                else
                {
                    currentCount = 0;
                    FullShoe = cards.shuffleDeck(FullShoe);
                    stats.Shoes++;
                    CurrentCardPostion = 1;
                    stats.Hand -= 1;
                }
            }
            if (updateGUIContinuously == false)
            {
                //Straight Stat Display
                displayStraightStats();

                //Dealer Probability Calculations
                calculateDealerProbability();

                //Player Probability Calculations
                calculatePlayerProbability();

                //House Advantage Calculations
                calculateHouseAdvantage();

                //Counting Stats
                displayCountingStats();
            }

            this.Update();
            Application.DoEvents();
        }

        private void CountingErrorAdjustment(RNGCryptoServiceProvider rnd, int PRand)
        {
            if (PRand <= errorRate)
            {
                //If an error occurs, randomly select wether the count is going to be higher or lower than actual
                int PRand2 = (GetNextInt32(rnd) % 2);
                int PRand3 = (GetNextInt32(rnd) % 4);
                PRand3++; //Creates a random number between 1 and 4 to be off by;
                if (PRand2 == 0)
                {
                    //Error High
                    currentCount = currentCount + PRand3;
                    stats.NumberOfErrors++;
                }
                else
                {
                    //Error Low
                    currentCount = currentCount - PRand3;
                    stats.NumberOfErrors++;
                }
            }
        }

        private void InsuranceDecision(int PlayerBet, bool DealerBlackJack)
        {
            //Only Consider Insurance when we are Counting
            if ((playerCounts) && (trueCount > 20))
            {
                if (DealerBlackJack)
                {
                    stats.InsuranceBetsWon++;
                    PlayerMoneyTotal = PlayerMoneyTotal + PlayerBet; //This adds the bet that is taken away below, therefore causing the player to break even on the hand.
                }
                else
                {
                    stats.InsuranceBetsLost++;
                    PlayerMoneyTotal = PlayerMoneyTotal - (PlayerBet / 2); //No blackjack so the player loses their insurance bet (half of their normal bet), then they play out the hand as normal.
                }
            }
        }

        private int BettingDecision(int TableMinimum, int TableMaximum, int BettingUnit)
        {
            int BetAdjusted = 0;
            if (playerCounts)
            {
                trueCount = Math.Round(((double)currentCount / (double)decksLeft), 1);
                trueCount = trueCount - TCAdjustment; //Subtract 1 form true if the rules are good, subtract 1.5 from ture if rules are bad.
                if (trueCount <= 1)
                {
                    BetAdjusted = (TableMinimum);
                    PlayerMoneyTotal -= BetAdjusted;
                }
                else
                {
                    if (trueCount > 1)
                    {
                        BetAdjusted = (int)Math.Round((BettingUnit * trueCount), 1);
                    }
                    if (BetAdjusted > TableMaximum)
                    {
                        BetAdjusted = TableMaximum;
                    }
                    PlayerMoneyTotal -= BetAdjusted;
                }

                if (stats.HighestBet < BetAdjusted)
                {
                    stats.HighestBet = BetAdjusted;
                }
                if (stats.HighestCount < trueCount)
                {
                    stats.HighestCount = trueCount;
                }
                if (stats.LowestCount > trueCount)
                {
                    stats.LowestCount = trueCount;
                }
                if (PlayerMoneyTotal < stats.LowestBankroll)
                {
                    stats.LowestBankroll = PlayerMoneyTotal;
                }
                if (PlayerMoneyTotal > stats.HighestBankroll)
                {
                    stats.HighestBankroll = PlayerMoneyTotal;
                }
            }
            else
            {
                //Place Flat Bet Normally
                BetAdjusted = (TableMinimum);
                PlayerMoneyTotal -= BetAdjusted;
            }
            return BetAdjusted;
        }

        private void displayStraightStats()
        {
            lblTotalHands.Text = Convert.ToString(stats.CalculateTotalHands());
            stats.TotalNonPushingHands = stats.CalculateTotalHands() - stats.Pushes;
            lblNonPushingTotal.Text = Convert.ToString(stats.TotalNonPushingHands);
            lblDealerWins.Text = Convert.ToString(stats.DealerWins);
            lblPlayerWins.Text = Convert.ToString(stats.PlayerWins);
            lblPushes.Text = Convert.ToString(stats.Pushes);
            lblShoes.Text = Convert.ToString(stats.Shoes);
            lblSplits.Text = Convert.ToString(stats.Splits);
            lblWinningDoubles.Text = Convert.ToString(stats.WinningDoubles);
            lblLosingDoubles.Text = Convert.ToString(stats.LosingDoubles);
            lblPushingDoubles.Text = Convert.ToString(stats.PushingDoubles);
            lblPlayerBankroll.Text = "$" + Convert.ToString(Math.Round(PlayerMoneyTotal - Convert.ToInt32(txtStartingBankRoll.Text), 2));
            lblTotalRounds.Text = Convert.ToString(stats.Hand);
            lblPlayerBlackjacks.Text = Convert.ToString(stats.PlayerBlackJacks);
            lblErrors.Text = Convert.ToString(stats.NumberOfErrors);
        }

        private void calculateDealerProbability()
        {
            lblDealerWinOnDouble.Text = Convert.ToString(Math.Round((stats.CalculateDealerWinOnDouble() * 100), 4)) + "%";
            lblDealerStraightWin.Text = Convert.ToString(Math.Round((stats.CalculateDealerWinStraight() * 100), 4)) + "%";
            lblDealerWinTotal.Text = Convert.ToString(Math.Round((stats.CalculateDealerProb() * 100), 4)) + "%";
            lblDealerCostWin.Text = Convert.ToString(Math.Round((stats.CalculateCostWeightedDealerWin() * 100), 4)) + "%";
        }

        private void calculatePlayerProbability()
        {
            lblWinOnDouble.Text = Convert.ToString(Math.Round((stats.CalculatePlayerWinOnDouble() * 100), 4)) + "%";
            lblWinOnBJ.Text = Convert.ToString(Math.Round((stats.CalculatePlayerWinOnBJ() * 100), 4)) + "%";
            lblPlayerStraightWin.Text = Convert.ToString(Math.Round((stats.CalculatePlayerWinStraight() * 100), 4)) + "%";
            lblPlayerWinTotal.Text = Convert.ToString(Math.Round((stats.CalculatePlayerProb() * 100), 4)) + "%";
            lblPlayerCostWin.Text = Convert.ToString(Math.Round((stats.CalculateCostWeightedPlayerWin() * 100), 4)) + "%";
        }

        private void calculateHouseAdvantage()
        {
            lblUnweightedAdv.Text = Convert.ToString(Math.Round((stats.CalculateUnweightedHouseAdv() * 100), 4)) + "%";
            lblHouseAdvantage.Text = Convert.ToString(Math.Round((stats.CalculateWeightedHouseAdv() * 100), 2)) + "%";
        }

        private void displayCountingStats()
        {
            lblHighestBet.Text = "$" + Convert.ToString(stats.HighestBet);
            lblHighestCount.Text = Convert.ToString(stats.HighestCount);
            lblLowestCount.Text = Convert.ToString(stats.LowestCount);
            lblLowestBankroll.Text = Convert.ToString(stats.LowestBankroll);
            lblHighestBankroll.Text = Convert.ToString(stats.HighestBankroll);
            lblInsuranceBetsLost.Text = Convert.ToString(stats.InsuranceBetsLost);
            lblInsuranceBetsWon.Text = Convert.ToString(stats.InsuranceBetsWon);
        }

        static int GetNextInt32(RNGCryptoServiceProvider rnd)
        {
            byte[] randomInt = new byte[4];
            rnd.GetBytes(randomInt);
            return Convert.ToInt32(randomInt[0]);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Width = 567;
            this.Height = 640;
            double Agression = (tbAgression.Value * 0.1);
            double ConservitiveUnit = (int)Math.Round((Convert.ToDouble(txtStartingBankRoll.Text) / 500), 0);
            int bettingUnitCalc = (int)Math.Round((ConservitiveUnit + (ConservitiveUnit * Agression)), 0);
            lblBettingUnit.Text = Convert.ToString(bettingUnitCalc);
        }

        private void rbCountFalse_CheckedChanged(object sender, EventArgs e)
        {
            
        }

        private void groupBox6_Enter(object sender, EventArgs e)
        {

        }

        private void tbAgression_Scroll(object sender, EventArgs e)
        {
            int i = 0;
            try
            {
                i = Convert.ToInt32(txtStartingBankRoll.Text);
                if ((i < 100) && (i > 10000000))
                {
                    txtStartingBankRoll.Text = "50000";
                    i = 50000;
                }
            }
            catch
            {
                txtStartingBankRoll.Text = "50000";
                i = 50000;
            }
            double Agression = (tbAgression.Value * 0.1);
            double ConservitiveUnit = (int)Math.Round(((double)i / 500), 0);
            int bettingUnitCalc = (int)Math.Round((ConservitiveUnit + (ConservitiveUnit * Agression)), 0);
            lblBettingUnit.Text = Convert.ToString(bettingUnitCalc);
        }

        private void txtStartingBankRoll_TextChanged(object sender, EventArgs e)
        {
            int i = 0;
            try
            {
                i = Convert.ToInt32(txtStartingBankRoll.Text);
                if ((i < 100) && (i > 10000000))
                {
                    txtStartingBankRoll.Text = "50000";
                    i = 50000;
                }
            }
            catch
            {
                txtStartingBankRoll.Text = "50000";
                i = 50000;
            }
            double Agression = (tbAgression.Value * 0.1);
            double ConservitiveUnit = (int)Math.Round(((double)i / 500), 0);
            int bettingUnitCalc = (int)Math.Round((ConservitiveUnit + (ConservitiveUnit * Agression)), 0);
            lblBettingUnit.Text = Convert.ToString(bettingUnitCalc);
        }

        private void rbFalse_CheckedChanged(object sender, EventArgs e)
        {
            if (rbFalse.Checked == true)
            {
                lblTCAdjustment.Text = "1";
            }
            else
            {
                lblTCAdjustment.Text = "1.5";
            }
        }

        private void cmdDetails_Click(object sender, EventArgs e)
        {
            if (this.Width == 885)
            {
                this.Width = 567;
                this.Height = 640;
            }
            else
            {
                this.Width = 885;
                this.Height = 640;
            }
        }

        private void rbErrorsOn_CheckedChanged(object sender, EventArgs e)
        {
            if (rbErrorsOn.Checked)
            {
                gbError.Enabled = true;
            }
            else
            {
                gbError.Enabled = false;
            }
        }

        private void rbErrorsOff_CheckedChanged(object sender, EventArgs e)
        {
            if (rbErrorsOn.Checked)
            {
                gbError.Enabled = true;
            }
            else
            {
                gbError.Enabled = false;
            }
        }

        private void gbError_Enter(object sender, EventArgs e)
        {

        }

        private void groupBox7_Enter(object sender, EventArgs e)
        {

        }

        private void tbErrorRate_Scroll(object sender, EventArgs e)
        {
            lblErrorsPer100Hands.Text = Convert.ToString(tbErrorRate.Value) + " errors per every 100 hands.";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                String outputPath = txtPath.Text;
                outputPath = outputPath.ToLower();
                if (!(outputPath.EndsWith(".txt")))
                {
                    outputPath = outputPath + ".txt";
                }
                StreamWriter sw = new StreamWriter(outputPath);
                sw.WriteLine("Highest Bankroll, Ending Bankroll, Lowest Bankroll");
                int numberOfIterations = Convert.ToInt16(numericUpDown1.Value);
                for (int i = 0; i < numberOfIterations; i++)
                {
                    cmdDeal_Click(null, null);
                    sw.WriteLine(stats.HighestBankroll + "," + PlayerMoneyTotal + "," + stats.LowestBankroll);
                }
                sw.Close();
                MessageBox.Show("Simulation Complete!");
            }
            catch
            {
                MessageBox.Show("You must enter a valid path, and number of iterations to run multiple simulations.");
            }
        }
    }
}